home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 008 / grepcode.lqr / grepcode.lbr / XTOOLS.C < prev   
Encoding:
C/C++ Source or Header  |  2011-01-27  |  7.3 KB  |  556 lines

  1. /*       Tools.c The expression parser used by grep.
  2.  */
  3.  
  4. #include "stdio.h"
  5. #include "tools.h"
  6.  
  7. /*
  8.  *    This module contains the various routines needed by grep
  9.  *    to match regular expressions. Routines are ordered alphabetically.
  10.  */
  11.  
  12. int    amatch( lin, pat, boln )
  13. char    *lin, *boln;
  14. TOKEN    *pat;
  15. {
  16.  
  17. register char    *bocl, *rval, *strstart;
  18.  
  19. if (pat == 0)
  20.     return (0);
  21.  
  22. strstart = lin;
  23.  
  24. while ( pat )
  25. {
  26.     if (pat->tok == CLOSURE && pat->next)
  27.     {
  28.         
  29.         pat = pat->next;
  30.  
  31.         bocl = lin;
  32.  
  33.          while ( *lin && omatch(&lin, pat, boln)  )
  34.             ;
  35.  
  36.         if (pat = pat->next)
  37.         {
  38.             while ( bocl <= lin )
  39.             {
  40.                 if (rval = amatch(lin, pat, boln) )
  41.                 {
  42.                     return(rval);
  43.                 }
  44.                 else
  45.                     --lin;
  46.             }
  47.             return (0);
  48.             }
  49.         }
  50.         else if ( omatch(&lin, pat, boln) )
  51.         {
  52.             pat = pat->next;
  53.         }
  54.         else
  55.         {
  56.             return (0);
  57.         }
  58.     }
  59.  
  60.     return ( max(strstart, --lin) );
  61. }
  62.  
  63.  
  64. delete( ch, str )
  65. int    ch;
  66. register char    *str;
  67. {
  68.     ch &= 0xff;
  69.  
  70.     while ( *str && *str != ch)
  71.         str++;
  72.  
  73.     while ( *str )
  74.     {
  75.         *str = *(str+1);
  76.         str++;
  77.     }
  78. }
  79.  
  80.  
  81. int    dodash(delim, src, dest, maxccl)
  82.  
  83. int    delim, maxccl;
  84. char    **src, *dest;
  85. {
  86.  
  87.     register char    *dstart;
  88.     register int    k, at_begin;
  89.     char        *sptr;
  90.  
  91.     dstart = dest;
  92.     sptr = *src;
  93.     at_begin = 1;
  94.  
  95.     while ( *sptr && (*sptr != delim) && (dest-dstart <maxccl) )
  96.     {
  97.         if ( *sptr == ESCAPE )
  98.         {
  99.             *dest++ = esc(&sptr);
  100.             sptr++;
  101.         }
  102.  
  103.         else if ( *sptr != '-')
  104.             *dest++ = *sptr++;
  105.  
  106.         else if ( at_begin || *(sptr+1) == delim )
  107.             *dest++ = '-';
  108.  
  109.         else if ( *(sptr -1 ) <= *(sptr+1) )
  110.         {
  111.             sptr++;
  112.  
  113.             for(k= *(sptr-2) ; ++k <= *sptr ;)
  114.                 *dest++ = k;
  115.  
  116.             sptr++;
  117.         }
  118.         else
  119.         {
  120.             return (0);
  121.         }
  122.  
  123.         at_begin = 0;
  124.     }
  125.  
  126.     *dest++ = '\000' ;
  127.     *src = sptr;
  128.  
  129.     return (dest - dstart);
  130. }
  131.  
  132.  
  133. int    esc(s)
  134. char    **s;
  135. {
  136.     register int    rval;
  137.  
  138.     if ( **s != ESCAPE)
  139.     {
  140.         rval = **s;
  141.     }
  142.     else
  143.     {
  144.         (*s)++;
  145.  
  146.         switch( toupper(**s) )
  147.         {
  148.         case '\000':    rval = ESCAPE;    break;
  149.         case 'S':     rval = ' ';    break;
  150.         case 'N':    rval = '\n';    break;
  151.         case 'T':    rval = '\t';    break;
  152.         case 'B':    rval = '\b';    break;
  153.         case 'R':    rval = '\r';    break;
  154.         default :    rval = **s ;    break;
  155.  
  156.         }
  157.     }
  158.  
  159.     return (rval);
  160. }
  161.  
  162.  
  163. TOKEN    *getpat( arg )
  164. char    *arg;
  165. {
  166.     return ( makepat(arg, '\000' ) );
  167. }
  168.  
  169.  
  170. insert( ch, str )
  171. int        ch;
  172. register char    *str;
  173. {
  174.  
  175.     register char    *bp;
  176.  
  177.     bp = str;
  178.  
  179.     while (*str)
  180.         str++;
  181.     do
  182.     {
  183.         *(str+1) = *str;
  184.         str--;
  185.  
  186.     } while (str >= bp);
  187.  
  188.     *bp = ch;
  189. }
  190.  
  191.  
  192. char    *in_string( delim, str )
  193. register int    delim;
  194. register char    *str;
  195. {
  196.  
  197.     delim &= 0x7f;
  198.  
  199.     while (*str && *str != delim)
  200.         str++;
  201.  
  202.     return ( *str ? str : 0 );
  203. }
  204.  
  205.  
  206. int isalphanum(c)
  207. int    c;
  208. {
  209.         return ( ('a' <= c && c <= 'z') ||
  210.              ('A' <= c && c <= 'Z') ||
  211.              ('0' <= c && c <= '9')
  212.                );
  213. }
  214.  
  215.  
  216. TOKEN    *makepat(arg, delim)
  217. char    *arg;
  218. int    delim;
  219. {
  220.  
  221.     TOKEN    *head, *tail;
  222.     TOKEN    *ntok;
  223.     char    buf[CLS_SIZE];
  224.     int    error;
  225.  
  226.     if (*arg=='\0' || *arg==delim || *arg=='\n' || *arg==CLOSURE)
  227.         return(0);
  228.  
  229.     error = 0;
  230.     head = 0;
  231.     tail = 0;
  232.  
  233.     while ( *arg && *arg != delim && *arg != '\n' && !error)
  234.     {
  235.         ntok = malloc( TOKSIZE );
  236.         ntok->string = &(ntok->lchar);
  237.         ntok->lchar = '\000';
  238.         ntok->next = 0;
  239.  
  240.         switch(*arg)
  241.         {
  242.         case ANY:
  243.             ntok->tok = ANY;
  244.             break;
  245.  
  246.         case BOL:
  247.  
  248.             if (head==0)
  249.                 ntok->tok = BOL;
  250.             else
  251.                 error = 1;
  252.             break;
  253.  
  254.         case EOL:
  255.             if ( *(arg+1) == delim || *(arg+1) == '\000'
  256.                            || *(arg+1) == '\n'   )
  257.                 ntok->tok = EOL;
  258.             else
  259.                 error = 1;
  260.             break;
  261.  
  262.         case CCL:
  263.             if (*(arg+1) == NEGATE)
  264.             {
  265.                 ntok->tok = NCCL;
  266.                 arg += 2;
  267.             }
  268.             else
  269.             {
  270.                 ntok->tok = CCL;
  271.                 arg++;
  272.             }
  273.  
  274.             error = dodash(CCLEND, &arg, buf, CLS_SIZE) ;
  275.             if (error != 0)
  276.             {
  277.                 ntok->string = malloc( error );
  278.                 strcpy( ntok->string, buf );
  279.                 error = 0;
  280.             }
  281.  
  282.             break;
  283.  
  284.         case CLOSURE:
  285.             if ( head != 0)
  286.             {
  287.                 switch ( tail->tok )
  288.                 {
  289.                 case BOL:
  290.                 case EOL:
  291.                 case CLOSURE:
  292.                     return(0);
  293.  
  294.                 default:
  295.                     ntok->tok = CLOSURE;
  296.                 }
  297.             }
  298.             break;
  299.  
  300.         default:
  301.             ntok->tok = LITCHAR;
  302.             ntok->lchar = esc(&arg);
  303.         }
  304.  
  305.         if( error || ntok == 0 )
  306.         {
  307.             unmakepat(head);
  308.             return (0);
  309.         }
  310.  
  311.         else if (head == 0)
  312.         {
  313.             ntok->next = 0;
  314.             head = tail = ntok;
  315.         }
  316.  
  317.         else if (ntok->tok != CLOSURE)
  318.  
  319.         {
  320.             tail->next = ntok;
  321.             ntok->next = tail;
  322.             tail = ntok;
  323.         }
  324.  
  325.         else if (head != tail)
  326.         {
  327.             (tail->next)->next = ntok;
  328.             ntok->next = tail;
  329.         }
  330.  
  331.         else
  332.         {
  333.             ntok->next = head;
  334.             tail->next = ntok;
  335.             head = ntok;
  336.         }
  337.  
  338.         arg++;
  339.     }
  340.     
  341.     tail->next = 0;
  342.     return (head);
  343. }
  344.  
  345.  
  346. char    *matchs(line, pat, ret_endp)
  347. char    *line;
  348. TOKEN    *pat;
  349. int    ret_endp;
  350. {
  351.  
  352.     char    *rval, *bptr;
  353.  
  354.     bptr = line;
  355.  
  356.     while (*line)
  357.     {
  358.         if ( (rval = amatch(line, pat, bptr)) == 0 )
  359.         {
  360.             line++;
  361.         }
  362.         else
  363.         {
  364.             rval = ret_endp ? rval : line ;
  365.             break;
  366.         }
  367.     }
  368.     
  369.     return (rval);
  370. }
  371.  
  372.  
  373. stoupper(str)
  374. char    *str;
  375. {
  376.  
  377.     char    *rval;
  378.  
  379.     rval = str;
  380.  
  381.     while (*str)
  382.     {
  383.         if ( 'a' <= *str && *str <= 'z' )
  384.             *str -= ('a' - 'A');
  385.  
  386.         str++;
  387.     }
  388.     return(rval);
  389. }
  390.  
  391.  
  392.  
  393. int    omatch (linp, pat, boln)
  394. char    **linp, *boln;
  395. TOKEN    *pat;
  396. {
  397.  
  398.     register int    advance;
  399.  
  400.     advance = -1;
  401.  
  402.     if ( **linp )
  403.     {
  404.         switch ( pat->tok )
  405.         {
  406.         case LITCHAR:
  407.             if ( **linp == pat->lchar )
  408.                 advance = 1;
  409.             break;
  410.  
  411.         case BOL:
  412.             if ( *linp == boln )
  413.                 advance = 0;
  414.             break;
  415.  
  416.         case ANY:
  417.             if ( **linp != '\n' )
  418.                 advance = 1;
  419.             break;
  420.  
  421.         case EOL:
  422.             if ( **linp == '\n' )
  423.                 advance = 0;
  424.             break;
  425.  
  426.         case CCL:
  427.             if( in_string (**linp, pat->string) )
  428.                 advance = 1;
  429.             break;
  430.  
  431.         case NCCL:
  432.             if ( ! in_string (**linp, pat->string ) )
  433.                 advance = 1;
  434.             break;
  435.  
  436.         default:
  437.             printf("omatch: can't happen\n");
  438.         }
  439.     }
  440.     
  441.     if (advance >= 0)
  442.         *linp += advance;
  443.  
  444.     return( ++advance );
  445. }
  446.  
  447.  
  448. pr_line(ln)
  449. register char    *ln;
  450. {
  451.  
  452.     for ( ; *ln ; ln++ )
  453.  
  454.     {
  455.         if ( (' ' <= *ln) && (*ln <= '~') )
  456.             putchar(*ln);
  457.         else
  458.         {
  459.             printf("\\0x%02x", *ln);
  460.  
  461.             if (*ln == '\n')
  462.                 putchar('\n');
  463.         }
  464.     }
  465. }
  466.  
  467.  
  468. pr_tok(head)
  469. TOKEN    *head;
  470. {
  471.     register char    *str;
  472.  
  473.     for (; head ; head = head->next )
  474.     {
  475.         switch (head->tok)
  476.         {
  477.         case BOL:
  478.             str = "BOL";
  479.             break;
  480.  
  481.         case EOL:
  482.             str = "EOL";
  483.             break;
  484.  
  485.         case ANY:
  486.             str = "ANY";
  487.             break;
  488.  
  489.         case LITCHAR:
  490.             str = "LITCHAR";
  491.             break;
  492.  
  493.         case ESCAPE:
  494.             str = "ESCAPE";
  495.             break;
  496.  
  497.         case CCL:
  498.             str = "CCL";
  499.             break;
  500.  
  501.         case CCLEND:
  502.             str = "CCLEND";
  503.             break;
  504.  
  505.         case NCCL:
  506.             str = "NCCL";
  507.             break;
  508.  
  509.         case CLOSURE:
  510.             str = "CLOSURE";
  511.             break;
  512.  
  513.         default:
  514.             str = "*** unknown ***";
  515.         }
  516.  
  517.         printf("%-8s at: 0x%x, ", str, head);
  518.  
  519.         if (head->tok == CCL || head->tok == NCCL)
  520.             printf ("string = [%s]=, ", head->string );
  521.  
  522.         else if (head->tok == LITCHAR)
  523.             printf("lchar = %c, ", head->lchar);
  524.  
  525.         printf("next = 0x%x\n", head->next);
  526.     }
  527.  
  528.     putchar('\n');
  529. }
  530.  
  531.  
  532. unmakepat(head)
  533. TOKEN     *head;
  534. {
  535.  
  536.     register TOKEN    *old_head;
  537.  
  538.     while (head)
  539.     {
  540.         switch (head->tok)
  541.         {
  542.         case CCL:
  543.         case NCCL:
  544.             free(head->string);
  545.     
  546.         default:
  547.             old_head = head;
  548.             head = head->next;
  549.             free(old_head);
  550.             break;
  551.         }
  552.     }
  553. }
  554.  
  555.  
  556.